#include "usart.h"  
#include "stm32f10x.h"                  // Device header  
#include "stdio.h"  
#include "pwm.h"

void usart3_init(int baud)  
{  
	    GPIO_InitTypeDef GPIO_InitStructure;  
	    NVIC_InitTypeDef NVIC_InitStruture;  
	    USART_InitTypeDef USART_InitStructure;  
    // 1. Enable GPIOB and USART3 clocks  
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);  
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);  

    // 2. Configure Rx and Tx pins for USART3  
    // PB11 ---> Rx  
    // PB10 ---> Tx  


    // PB11 --> Rx  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;    // Floating input for Rx  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;               // PB11  
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;  
    GPIO_Init(GPIOB, &GPIO_InitStructure);  

    // PB10 --> Tx  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;          // Alternate function push-pull for Tx  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;               // PB10  
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;  
    GPIO_Init(GPIOB, &GPIO_InitStructure);  

    // 3. Configure USART parameters  

    USART_InitStructure.USART_BaudRate = baud;                                        // Set baud rate  
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;    // No flow control  
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;                    // Enable Rx and Tx  
    USART_InitStructure.USART_Parity = USART_Parity_No;                                // No parity  
    USART_InitStructure.USART_StopBits = USART_StopBits_1;                            // 1 stop bit  
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;                        // 8 data bits  
    USART_Init(USART3, &USART_InitStructure);  

    // 4. Enable USART  
    USART_Cmd(USART3, ENABLE);  
    
    // Enable RX interrupt  
    USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);  

    // NVIC configuration  

    NVIC_InitStruture.NVIC_IRQChannel = USART3_IRQn;  
    NVIC_InitStruture.NVIC_IRQChannelCmd = ENABLE;  
    NVIC_InitStruture.NVIC_IRQChannelPreemptionPriority = 0;    // Preemption priority  
    NVIC_InitStruture.NVIC_IRQChannelSubPriority = 1;           // Subpriority  
    NVIC_Init(&NVIC_InitStruture);  
}  

void USART3_IRQHandler(void)  
{  
    if (SET == USART_GetITStatus(USART3, USART_IT_RXNE))          // Check if RX interrupt has occurred  
    {  
        unsigned char data = recv_byte();  
				M_ctr(data);
        send_byte(data);                                          // Echo received data  
    }  
    USART_ClearITPendingBit(USART3, USART_IT_RXNE);              // Clear the interrupt flag  
}  

// 5. Function to send a string  
void send_str(char *str)  
{  
    while (*str != '\0')                                         // Loop until null terminator  
    {  
        send_byte((unsigned char)*str);                          // Send each character  
        str++;                                                   // Move to the next character  
    }  
}  

// Send a single byte  
void send_byte(unsigned char ch)  
{  
    USART_SendData(USART3, ch);  
    while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET); // Wait until transmission is complete  
}  

// Receive a byte  
unsigned char recv_byte(void)  
{  
    unsigned char data;  
    while (USART_GetFlagStatus(USART3, USART_FLAG_RXNE) == RESET); // Wait until data is received  
    data = USART_ReceiveData(USART3);  
    return data;  
}  

// Override fputc function for printf redirection  
int fputc(int ch, FILE *file)  
{  
    send_byte(ch);  
    return ch;  
}

